package com.desay.pangoo.itmt.service.impl;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import com.desay.pangoo.common.lite.lang.web.BusinessException;
import com.desay.pangoo.common.lite.lang.web.PangooWebConstant;
import com.desay.pangoo.common.lite.spring.web.ControllerCommonUtils;
import com.desay.pangoo.itmt.config.AICompletionProperties;
import com.desay.pangoo.itmt.config.TechOnlineReviewSchedule;
import com.desay.pangoo.itmt.controller.vo.TechNewsVo;
import com.desay.pangoo.itmt.entity.OrgChartEntity;
import com.desay.pangoo.itmt.entity.TechNewsEntity;
import com.desay.pangoo.itmt.entity.TechNewsFeedbackEntity;
import com.desay.pangoo.itmt.entity.WorkGroupEntity;
import com.desay.pangoo.itmt.enums.ExceptionCodeEnum;
import com.desay.pangoo.itmt.repository.OrgChartRepository;
import com.desay.pangoo.itmt.repository.TechNewsFeedbackRepository;
import com.desay.pangoo.itmt.repository.TechNewsRepository;
import com.desay.pangoo.itmt.repository.WorkGroupRepository;
import com.desay.pangoo.itmt.repository.spec.ExpandCriteria;
import com.desay.pangoo.itmt.repository.spec.Restrictions;
import com.desay.pangoo.itmt.service.TechNewsService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;

/**
 * @author uidq1163
 */
@Slf4j
@Service
public class TechNewsServiceImpl implements TechNewsService {

	@Autowired
	TechNewsRepository techNewsRepository;

	@Autowired
	TechNewsFeedbackRepository techNewsFeedbackRepository;

	@Autowired
	private WorkGroupRepository workGroupRepository;

	@Autowired
	TechOnlineReviewSchedule techOnlineReviewSchedule;

	@Autowired
	private OrgChartRepository orgChartRepository;
	@Autowired
	private AICompletionProperties aiCompletionProperties;
	/**
	 * 组织角色:ITMT ChairMan:1，ITMT Leader:2，ITMT
	 * SubLeader:3，ITMT成员:4,TSP:5,PRG:6,秘书长：7，委员：8,统筹人：9,
	 */
	private static final List<Integer> ORG_ROLES = List.of(2, 3, 7, 8, 9);

	/**
	 * 创建一个自定义配置的线程池 corePoolSize（2）：核心线程池大小，线程池中始终保留的线程数，即使它们处于空闲状态。
	 * maximumPoolSize（4）：线程池的最大线程数，线程池在需求增加时可以创建的最大线程数。
	 * keepAliveTime（60L）：超过corePoolSize 的线程空闲时的存活时间。
	 * unit（TimeUnit.SECONDS）：keepAliveTime 的时间单位。 workQueue（new
	 * LinkedBlockingQueue<>(100)）：任务队列，当所有核心线程都在运行时，新的任务会放到这个队列中。 handler（new
	 * ThreadPoolExecutor.CallerRunsPolicy()）：饱和策略，当任务队列已满且线程池中的线程数已达到
	 * maximumPoolSize 时，任务会由提交任务的线程执行
	 */
	ExecutorService executorService = new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS,
			new LinkedBlockingQueue<>(100), new ThreadPoolExecutor.CallerRunsPolicy());

	@Override
	public Long create(TechNewsVo vo) {
		String user = ControllerCommonUtils.getHeader(PangooWebConstant.HEADER_NAME_USER_FULL_NAME);
		TechNewsEntity entity = new TechNewsEntity();
		if (null != vo.getWorkGroupId()) {
			// 检查工作组是否存在
			Optional<WorkGroupEntity> option = workGroupRepository.findById(vo.getWorkGroupId());
			if (option.isPresent()) {
				entity.setWorkGroup(option.get());
			} else {
				throw new BusinessException(ExceptionCodeEnum.WORK_GROUP_NOT_EXIST);
			}
		}
		entity.setTechUrl(vo.getTechUrl());
		entity.setTechContext(vo.getTechContext());
		entity.setTechTitle(vo.getTechTitle());
		entity.setCreator(user);
		entity.setImageInfo(vo.getImageInfo());
		techNewsRepository.save(entity);

		// 推送消息任务
		executorService.submit(() -> {
			Set<OrgChartEntity> list = orgChartRepository.findByOrgRoleIn(ORG_ROLES);
			if (null != entity.getWorkGroup()) {
				// 如果选择了域，就通知到这个域的TMT成员
				Set<OrgChartEntity> tmt = orgChartRepository.findByWorkGroup(entity.getWorkGroup());
				list.addAll(tmt);
			}
			List<String> leaders = list.stream().map(o -> o.getLogin()).toList();
			// 推送yesv消息
			techOnlineReviewSchedule.pushTechNewToUsers(leaders, entity.getId(), vo.getTechTitle());
		});

		// 新闻摘要任务
		executorService.submit(() -> {
			JSONObject requestBody = new JSONObject();
			if (StringUtils.isNotEmpty(entity.getTechUrl())) {
				requestBody.set("url", entity.getTechUrl());
			} else {
				requestBody.set("doc", entity.getTechContext());
			}
			// 生成新闻摘要
			String summary = generateSummary(requestBody);
			// 回写更新字段
			entity.setTechAbstract(summary);
			techNewsRepository.save(entity);
		});
		return entity.getId();
	}

	@Override
	public void addFaceBack(TechNewsVo vo) {
		String user = ControllerCommonUtils.getHeader(PangooWebConstant.HEADER_NAME_USER_FULL_NAME);
		TechNewsFeedbackEntity entity = new TechNewsFeedbackEntity();
		entity.setIsApproval(vo.getIsApproval());
		entity.setRemark(vo.getRemark());
		entity.setCreator(user);
		entity.setParent(techNewsRepository.findById(vo.getId()).get());
		techNewsFeedbackRepository.save(entity);
	}

	@Override
	public Page<TechNewsEntity> getAll(Long workGroupId, Integer pageSize, Integer pageNum) {
		ExpandCriteria<TechNewsEntity> c = new ExpandCriteria<>();
		// 根据组查询
		c.add(Restrictions.eq("workGroup.id", workGroupId, true));
		// 根据组查询
		List<Sort.Order> orders = new ArrayList<>();
		Sort.Order order = new Sort.Order(Sort.Direction.DESC, "createTime");
		orders.add(order);
		Pageable pageReq = PageRequest.of(pageNum - 1, pageSize, Sort.by(orders));
		Page<TechNewsEntity> page = techNewsRepository.findAll(c, pageReq);
		List<TechNewsEntity> list = page.getContent().stream().map(item -> {
			TechNewsEntity entity = new TechNewsEntity();
			BeanUtils.copyProperties(item, entity);
			// 统计反馈数量
			entity.setImageInfo(null);
			return entity;
		}).toList();
		page = new PageImpl<>(list, pageReq, page.getTotalElements());
		return page;
	}

	@Override
	public TechNewsEntity getTechNews(Long id) {
		return techNewsRepository.findById(id).get();
	}

	/**
	 * 技术信息反馈列表
	 * 
	 * @param id
	 * @return
	 */
	@Override
	public List<TechNewsFeedbackEntity> getFaceBackList(Long id) {
		ExpandCriteria<TechNewsFeedbackEntity> c = new ExpandCriteria<>();
		// 根据组查询
		c.add(Restrictions.eq("parent.id", id, true));
		return techNewsFeedbackRepository.findAll(c);
	}

	@Override
	public List<JSONObject> report(String startDate, String endDate) {
		ExpandCriteria<TechNewsEntity> c = new ExpandCriteria<>();
		Date startTime = DateUtil.parse(startDate);
		Date endTime = DateUtil.parse(endDate);
		// 根据组查询
		c.add(Restrictions.gte("createTime", startTime, true));
		c.add(Restrictions.lte("createTime", endTime, true));
		List<TechNewsEntity> list = techNewsRepository.findAll(c);

		// 统计
		// 使用映射优化查找性能
		Map<Long, List<TechNewsFeedbackEntity>> feedbackMap = techNewsFeedbackRepository.findByParentIn(list).stream()
				.collect(Collectors.groupingBy(fb -> fb.getParent().getId()));

		List<JSONObject> result = new ArrayList<>();
		for (TechNewsEntity item : list) {
			JSONObject itemResult = new JSONObject();
			result.add(itemResult);
			itemResult.set("techTitle", item.getTechTitle());
			itemResult.set("techAbstract", item.getTechAbstract());

			// 使用映射获取反馈列表，避免重复查找
			List<TechNewsFeedbackEntity> feedBack = feedbackMap.getOrDefault(item.getId(), Collections.emptyList());
			itemResult.set("approveCount", feedBack.stream().filter(TechNewsFeedbackEntity::getIsApproval).count());
			itemResult.set("rejectCount", feedBack.stream().filter(fb -> !fb.getIsApproval()).count());
		}

		return result;
	}

	public String generateSummary(JSONObject requestBody) {
		// 最大重试次数
		final int maxRetries = 5;
		// 重试间隔
		final long retryDelayMillis = 5000;
		HttpResponse response = null;
		String url = aiCompletionProperties.getUri() + aiCompletionProperties.getToolSummary();
		for (int i = 0; i <= maxRetries; i++) {
			try {
				if (i > 0) {
					// 不是第一次尝试时，才等待
					Thread.sleep(retryDelayMillis);
				}
				response = HttpRequest.post(Objects.requireNonNull(url, "generateHost cannot be null"))
						.header("Content-Type", "application/json").body(requestBody.toString()).execute();
				if (response != null && response.getStatus() == HttpStatus.OK.value()) {
					// 成功获取响应体后直接返回
					return response.body();
				}
			} catch (InterruptedException e) {
				// 恢复中断状态
				Thread.currentThread().interrupt();
				log.error("摘要生成被中断", e);
				return "生成摘要信息被中断";
			} finally {
				if (response != null) {
					// 假设 HttpResponse 类提供了 close 方法来释放资源
					response.close();
				}
			}
		}
		log.error("摘要生成失败--{}", requestBody.toString());
		return "生成摘要信息失败";
	}
}
